<html>
<head><meta charset="utf-8"><title>new type safe to transmute to inner · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html">new type safe to transmute to inner</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="232900912"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232900912" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lukas Bergdoll <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232900912">(Apr 02 2021 at 13:51)</a>:</h4>
<p>Is it safe to transmute a new type into the inner type eg: <code>struct NewType(T)</code> -&gt; <code>T</code> and vice versa? Naively I'm assuming they should be layout compatible.</p>



<a name="232902726"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232902726" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232902726">(Apr 02 2021 at 14:08)</a>:</h4>
<p>It is only guaranteed if <code>NewType</code> is marked <code>#[repr(transparent)]</code></p>



<a name="232904150"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232904150" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232904150">(Apr 02 2021 at 14:22)</a>:</h4>
<p>repr(C) would do it as well</p>



<a name="232920787"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232920787" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232920787">(Apr 02 2021 at 16:38)</a>:</h4>
<p><code>#[repr(C)]</code> is fine if the transmuted type is a function pointer where <code>NewType</code> or <code>T</code> is an argument or return type. For example transmuting <code>fn(NewType)</code> to <code>fn(T)</code> is not allowed when <code>NewType</code> is not <code>#[repr(transparent)]</code>. Some calling conventions use a different pass mode for integers and integer struct wrappers. Only <code>#[repr(transparent)]</code> ensures an identical pass mode.</p>



<a name="232925385"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232925385" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232925385">(Apr 02 2021 at 17:12)</a>:</h4>
<blockquote>
<p>Naively I'm assuming they should be layout compatible.</p>
</blockquote>
<p>A sufficiently advanced compiler doing whole program analysis might see that your newtype (unlike the wrapped one) is mostly used in arrays and it would be beneficial to use simd operations on them and thus decides to bump its alignment to be more simd-friendly. This would at least make T -&gt; newtype transmutes incorrect.</p>



<a name="232925860"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232925860" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232925860">(Apr 02 2021 at 17:16)</a>:</h4>
<p>rustc isn't doing that right now, but for such an optimization to be allowed in the future the absence of layout guarantees is important</p>



<a name="232929419"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232929419" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232929419">(Apr 02 2021 at 17:42)</a>:</h4>
<p><span class="user-mention silent" data-user-id="118745">Lukas Bergdoll</span> <a href="#narrow/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner/near/232900912">said</a>:</p>
<blockquote>
<p>Naively I'm assuming they should be layout compatible.</p>
</blockquote>
<p>Philosophically, Rust tends to prefer that if you're relying on something there's a marker in the code about it somehow.  That means the compiler can help you by failing if it were ever changed to <code>struct NewType(T, bool);</code>, or it could add extra checking to non-transparent types in debug or something by tracking extra state in the type.</p>



<a name="232998901"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232998901" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232998901">(Apr 03 2021 at 11:06)</a>:</h4>
<p>Hmm, it looks like there is an ambiguity in this thread that leads to seemingly different answers:</p>
<ul>
<li>if you are actually transmuting a <code>Wrappee</code> to a <code>NewTypeWrapper</code> and <em>vice versa</em>, then:<ul>
<li><code>#[repr(C)]</code> suffices,</li>
<li><code>#[repr(transparent)]</code> works too, and is a bit more constraining on the actual definition of <code>NewTypeWrapper</code>, making the pattern a bit more resilient to refactoring. It should thus be preferred when possible.</li>
<li>It should be noted that transmuting seems overkill here, since a "manual" wrapping / into_inner operation will achieve the same (barring privacy constructor / pattern destructor concerns, or drop impls for destructuring)</li>
<li><code>#[repr(Rust)]</code> (the default when no repr annotation is around) <strong>will also be fine</strong>, soundness-wise, provided <code>mem::transmute</code> is used. Indeed, if it compiles, it means they have the same size. Stability-wise, however, you could get compilation breakage from the size of the newtype changing (I doubt that will happen, but it technically can). In that regard, <span class="user-mention" data-user-id="330154">@The 8472</span> is not totally right: alignment alone does not matter when transmuting by value (except when the alignment becomes bigger than the intrinsic size, since that will lead to a stride that is bundled within the effective size, thus changing it).</li>
</ul>
</li>
<li>If transmuting a composite type, stuff becomes way more subtle:<ul>
<li>If transmuting simple pointer / reference types (<em>a.k.a.</em>, casting), then you will indeed need to have the actual pointer be aligned to the destination type's alignment, and for reference types it is sufficient that the two types have the same alignment, which is possible to guarantee with <code>#[repr(C)]</code> and no extra fields nor alignment annotations, or by a <code>#[repr(transparent)]</code>. This makes <code>#[repr(Rust)]</code> quite ill-suited for the task.</li>
<li><strong>if transmuting function pointer types, then <code>#[repr(transparent)]</code> is mandatory</strong> (any other repr does not suffice).</li>
<li>if transmuting a composite type, <em>e.g.</em>, <code>Foo&lt;Wrappee&gt;</code> to/from <code>Foo&lt;NewTypeWrapper&gt;</code>, then, nothing is guaranteed, not even with <code>#[repr(transparent)]</code> (consider, for instance, <code>Foo = Option</code> and <code>UnsafeCell&lt;TypeWithNiche&gt;</code>). You will have to "study" the transmutability on a case per case basis.</li>
</ul>
</li>
</ul>



<a name="232999125"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/232999125" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#232999125">(Apr 03 2021 at 11:11)</a>:</h4>
<p>Note that all this relates to type layout: about not breaking the most frequent <em>validity</em> invariants of the types involved. </p>
<p>Observing, for instance, that <code>NonZeroU32</code> is a transparent wrapper around <code>u32</code> shows that the wrapper can add extra validity invariants, which would make these transmutations unsound in the general case, unless extra checks were to be added.</p>
<p>But even barring this <em>niche</em> case (heh), the newtype wrapper can also add (or remove!) <em>safety</em> invariants <em>w.r.t.</em> its wrappee, so care should be taken not to break any of these</p>



<a name="233017419"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/new%20type%20safe%20to%20transmute%20to%20inner/near/233017419" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/new.20type.20safe.20to.20transmute.20to.20inner.html#233017419">(Apr 03 2021 at 16:43)</a>:</h4>
<p>Yeah, I assumed the question was about general transmutability which might be done either by pointer access or by value. Doing one but avoiding the other is more subtle.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>